/*
 * Copyright (C) 2011 Young,Fey <fey.young@gmail.com>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package com.youngfey.wordnet
import groovy.util.logging.*
import groovy.transform.*
import com.youngfey.util.*
import edu.smu.tspell.wordnet.*

/**
 * WordNet数据库，所有查找操作均通过该类完成
 * @author Young,Fey <fey.young@gmail.com>
 */
@Log
class WordNet {
    static WordNet getInstance() { new WordNet() }
    private static final prop = 'wordnet.database.dir'

    private WordNet() { load() }

    /**
     * 根据单词的拼写猜测单词原型，可以应用于虚构的单词
     * @return 可能的单词原型，不包括token的原始拼写
     */
    Set<String> getBaseFormCandidates(String token, boolean caseSensitive = false) {
        def key = caseSensitive ? token : token.toLowerCase() 
        def cs = SynsetType.ALL_TYPES.collect { type ->
            database.getBaseFormCandidates(key, type)
        }.flatten() as Set
        cs ? cs : [token] as Set
    }

    /**
     * 根据给定的拼写查找Lemma
     * @param morphology 当该参数为真时，所有语义相关的词条均会返回。例如查找'lies'时，'rest'
     * 或'consist'等词汇。
     */
    Map<String, Lemma> getLemmas(String token, boolean morphology = false,
            boolean caseSensitive = false) {
        def synsets = database.getSynsets(caseSensitive? token : token.toLowerCase())
        def lemmas = [:]
        def baseForms = getBaseFormCandidates(token, caseSensitive)
        synsets.each { synset ->
            synset.wordForms.findAll {
                morphology || baseForms.contains(it) || it == token
            }.each { form ->
                if(!lemmas.containsKey(form))
                    lemmas.put(form, new Lemma(form, [] as Set))
                lemmas.get(form).synsets << synset
            }
        }
        lemmas
    }

    //尝试加载数据库
    private load() {
        if(!System.getProperty(prop)) {
            log.info 'No Wordnet property'
            final home = System.getProperties().'user.home'
            def dir = new File(home, '.wordnet')
            def dict = new File(dir, 'dict')
            if(!dict.exists()) {
                log.info 'Try to copy WordNet database'
                assert ResourceUtil.extractDir('dict', dict),
                    "Failed to copy the database"
            }
            ['data.adj', 'index.sense', 'data.noun', 'data.verb',
            'index.adj', 'index.verb', 'data.adv',
            'index.noun', 'index.adv'].each {
                assert new File(dict, it).exists()
            }
            System.setProperty(prop, dict.absolutePath)
        }
        database = WordNetDatabase.getFileInstance()
    }

    private database
}

